package com.lxy.skill.server.impl;

import com.alibaba.fastjson.JSONObject;
import com.lxy.skill.server.SecKillServer;
import com.lxy.skill.util.CuratorUtil;
import com.lxy.skill.util.RedisUtil;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author lxy
 * @Date 2021/12/19 13:15
 * @Description
 */

@Service
public class SecKillServerImpl implements SecKillServer {

    @Autowired
    private static RedisUtil redisUtil;

    @Autowired
    private Redisson redisson;

    @Autowired
    private static RabbitTemplate rabbitTemplate;

    @Autowired
    private CuratorUtil curatorUtil;

    public static boolean redisOpera(String sid,String uid){
        String kcKey = "sk:" + sid + ":kc";
        String kcMap = "sk:" + sid + ":map";
        int kc = Integer.parseInt(redisUtil.get(kcKey).toString());
        boolean have = redisUtil.hHasKey(kcMap, uid);
        if(have == false){
            if(kc > 0){
                int surpluskc = kc-1;
                redisUtil.hset(kcMap,uid,true);
                redisUtil.set(kcKey,surpluskc+"");
                Map<String,Object> map=new HashMap<>();
                map.put("sid",sid);
                map.put("uid",uid);
                //将消息携带绑定键值：TestDirectRouting 发送到交换机TestDirectExchange
                String json = JSONObject.toJSONString(map);
                rabbitTemplate.convertAndSend("DirectExchange", "DirectRouting", json);
                System.out.println("秒杀成功，剩余库存："+surpluskc);
                return true;
            }else{
                System.out.println("秒杀失败，库存不足");
            }
        }else{
            System.out.println("不可重复抢购");
        }
        return false;
    }

    @Override
    public boolean skillRedisson(String sid, String uid) {
        if(sid == null && uid == null){
            return false;
        }
        String lock = "seclock"+sid;
        RLock seclock = redisson.getLock(lock);
        try {
            seclock.lock();
            System.out.println("rlock获取锁成功");
            boolean b = redisOpera(sid, uid);
            return b;
        }finally {
            seclock.unlock();
        }
    }

    @Override
    public boolean skillZookeeper(String sid, String uid) throws Exception {
        if(sid == null && uid == null){
            return false;
        }
        String path = "/seclock" + sid;
        CuratorFramework zkClient = curatorUtil.lock();
        InterProcessMutex lock = new InterProcessMutex(zkClient, path);
        try{
            if(lock.acquire(3000, TimeUnit.MILLISECONDS)) {
                System.out.println("zk加锁成功");
                boolean b = redisOpera(sid, uid);
                return b;
            }else {
                System.out.println("zk加锁失败");
                return false;
            }
        }finally {
            lock.release();
            zkClient.close();
        }
    }
}
